﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Util;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;

namespace XmrStakWin64
{
    class XmrStakWin64Helper
    {
        /// <summary>
        /// 单例
        /// </summary>
        private static XmrStakWin64Helper instance;

        /// <summary>
        /// 当前的状态
        /// </summary>
        private ConstantHolderUtil.CORE_STATE state = ConstantHolderUtil.CORE_STATE.CORE_IDLE;

        /// <summary>
        /// 连接exe读取及时信息使用
        /// </summary>
        private SocketHelper.TcpClients client;

        private int _benchmarkCount;
        private double _benchmarkSum;
        /// <summary>
        /// 工作目录
        /// </summary>
        private string dir = string.Empty;
        private string cmdFileName = string.Empty;
        private string cmdFilePara = string.Empty;
        /// <summary>
        ///是否连接成功
        /// <summary>
        public bool isConnect;

        public XmrStakWin64JsonResult jResult;
        /// <summary>
        ///运行时间
        /// <summary>
        public string runningTime;

        public double totalSpeed;
        /// <summary>
        ///分速度
        /// <summary>
        public float[] speeds = new float[30];
        /// <summary>
        ///设备的share
        /// <summary>
        public int accepted_shares;
        /// <summary>
        ///设备的reject
        /// <summary>
        public int rejected_shares;

        /// <summary>
        /// 解的个数？
        /// </summary>
        public int[] solver = new int[30];
        /// <summary>
        /// 温度
        /// </summary>
        public int temperature;
        /// <summary>
        /// gpu使用电量
        /// </summary>
        public int gpu_power_usage;

        /// <summary>
        /// 进程开始信息
        /// </summary>
        private ProcessStartInfo startInfo = null;
        /// <summary>
        /// 进程
        /// </summary>
        private Process process = new Process();

        /// <summary>
        /// 获取信息的线程
        /// </summary>
        Thread getInfoThread = null;

        /// <summary>
        /// 保护构造方法
        /// </summary>
        protected XmrStakWin64Helper()
        {
            //生成工作目录
            //dir = "H:\\HashcatEnigma_Release_1.1.0006.0281\\HashcatEnigma\\Data\\Bin\\Miner" + "\\" + ConstantHolderUtil.STM_PATH[5];
            //dir = "F:\\HashcatEnigma\\Data\\Bin\\Miner" + "\\" + ConstantHolderUtil.STM_PATH[5];
            //dir = "C:\\HashcatEnigma\\Data\\Bin\\Miner" + "\\" + ConstantHolderUtil.STM_PATH[5];
            dir = ConstantHolderUtil.GetInstance().DATA_DIRECTORY + "\\" + "xmr-stak";

            //文件全名
            cmdFileName = dir + "\\" + "xmr-stak.exe ";
            
        }
        /// <summary>
        /// 处理推送过来的消息
        /// </summary>
        /// <param name="rec"></param>
        private void Rec(SocketHelper.Sockets sks)
        {
            if (sks.ex != null)
            {
                //在这里判断ErrorCode  可以自由扩展
                switch (sks.ErrorCode) 
                {
                    case SocketHelper.Sockets.ErrorCodes.objectNull:
                        break;
                    case SocketHelper.Sockets.ErrorCodes.ConnectError:
                        Helpers.ConsolePrint("XmrStakWin64Helper", "Sockets Connect Error" + sks.ex.ToString());
                        isConnect = false;
                        break;
                    case SocketHelper.Sockets.ErrorCodes.ConnectSuccess:
                        //statuslist.Items.Add("连接成功.!");
                        break;
                    case SocketHelper.Sockets.ErrorCodes.TrySendData:
                        break;
                    default:
                        break;
                }
                
                //MessageBox.Show(sks.ex.ToString(), "推送过来的错");
            }
            else
            {
                byte[] buffer = new byte[sks.Offset];
                Array.Copy(sks.RecBuffer, buffer, sks.Offset);
                string str = Encoding.UTF8.GetString(buffer);

                if (str != "")
                {
                    RecDo(str);
                    isConnect = true;
                }
            }
        }

        /// <summary>
        /// 处理字符串
        /// </summary>
        /// <returns></returns>
        public void RecDo(string str)
        {
            if (str.Contains("HTTP")) 
            {
                return;
            }
            XmrStakWin64JsonModel jo = JsonConvert.DeserializeObject<XmrStakWin64JsonModel>(str);
            jResult = jo.results;
            accepted_shares = jo.results.shares_good;
            rejected_shares = jo.results.shares_total;
            speeds[0] = jo.hashrate.highest;
            double?[] tep = jo.hashrate.total;
            //totalSpeed = tep[1].Value;

            _benchmarkCount = 0;
            _benchmarkSum = 0;
            for (int i = 0; i < 3; i++)
            {
                if (tep[i] !=null && tep[i].Value != 0)
                {
                    _benchmarkSum += tep[i].Value;
                    _benchmarkCount++;
                }
            }
            totalSpeed = _benchmarkSum / Math.Max(1, _benchmarkCount);
            //totalSpeed = jo.hashrate.highest;
            //foreach (var item in tep)
            //{
            //    if (item != null)
            //    {
            //        totalSpeed += item.Value;
            //    }
            //}
        }

        /// <summary>
        /// 开始取数据
        /// </summary>
        /// <returns></returns>
        private void GetStateInfo()
        {
            bool isSTM_EXELive = true;
            do
            {
                Thread.Sleep(2000);
                //连接失败返回
                if (!client.client.Connected)
                {
                    bool isconet = client.RestartInit();
                }
                //发送http get请求
                string h1 = "GET " + "/api.json" + " HTTP/1.1\r\n";
                string h2 = "Accept: */*\r\n";
                string h3 = "Accept-Language: zh-cn\r\n";
                string h4 = "Host: " + ConstantHolderUtil.XMRSTAK_IP+":"+ ConstantHolderUtil.XMRSTAK_PORT + "\r\n";
                string h5 = "User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36\r\n";
                string h7 = "Connection: close\r\n\r\n";

                string strtep = h1 + h2 + h3 + h4 + h5 + h7;

                client.SendData(strtep);

                //停止xmr-stak
                Process[] p = Process.GetProcesses();
                isSTM_EXELive = false;
                foreach (Process p1 in p)
                {
                    string processName = p1.ProcessName.ToLower().Trim();
                    //判断是否进程活着
                    if (processName == "xmr-stak")
                    {
                        isSTM_EXELive = true;
                        break;
                    }
                }
            } while (isSTM_EXELive == true);
            //cmd意外关闭进行重启
            if (state == ConstantHolderUtil.CORE_STATE.CORE_BUSY)
            {
                restart();
            }
        }

        /// <summary>
        /// 获得单例
        /// </summary>
        /// <returns></returns>
        public static XmrStakWin64Helper GetInstance()
        {
            if (instance == null)
            {
                instance = new XmrStakWin64Helper();
            }
            return instance;
        }
        /// <summary>
        /// 自定义参数运行
        /// </summary>
        /// <returns>0为正常，1为出错，2为状态正忙</returns>
        public int Start(string FilePara)
        {

            cmdFilePara = FilePara.Trim();
            Helpers.ConsolePrint("XmrStakWin64Helper", "start miner");
            if (state == ConstantHolderUtil.CORE_STATE.CORE_IDLE)
            {
                try
                {
                    //设置状态
                    state = ConstantHolderUtil.CORE_STATE.CORE_BUSY;
                    //result = "";
                    Helpers.ConsolePrint("XmrStakWin64Helper", "init Socket");
                    //客户端如何处理异常等信息参照服务端
                    //SocketHelper.pushSockets = new SocketHelper.PushSockets(Rec);//注册推送器
                    client = new SocketHelper.TcpClients();
                    client.InitSocket(ConstantHolderUtil.XMRSTAK_IP, ConstantHolderUtil.XMRSTAK_PORT, new SocketHelper.PushSockets(Rec));
                    isConnect = false;
                    runningTime = string.Empty;

                    //startInfo = new ProcessStartInfo("cmd.exe", "/C \"\"" + dir + "\\" + cmdFileName + ".exe\" " + cmdFilePara + "\"");
                    //cmd运行参数
                    //foreach (string arg in ConstantHolderUtil.XMRSTAK_ARG)
                    //{
                    //    cmdFilePara = cmdFilePara + arg + " ";
                    //}
                    //cmdFilePara = cmdFilePara.Trim();
                    Helpers.ConsolePrint("XmrStakWin64Helper", "start miner cmd");
                    startInfo = new ProcessStartInfo(cmdFileName, cmdFilePara);
                    startInfo.WorkingDirectory = dir;
                    //不创建窗口
                    //startInfo.WindowStyle = ProcessWindowStyle.Normal;
                    //通过以下参数可以控制exe的启动方式，具体参照 myprocess.StartInfo.下面的参数，如以无界面方式启动exe等
                    process.StartInfo.UseShellExecute = false;
                    //设置启动动作,确保以管理员身份运行
                    startInfo.Verb = "runas";

                    //开始运行
                    process = Process.Start(startInfo);

                    //process = Process.Start(cmdFileName, cmdFilePara);

                    Helpers.ConsolePrint("XmrStakWin64Helper", "start new Thread for Socket Send request");
                    //从输出获取信息
                    getInfoThread = new Thread(GetStateInfo);
                    getInfoThread.Start();

                    return 0;
                }
                catch (Exception runException)
                {
                    Helpers.ConsolePrint("XmrStakWin64Helper", "start Miner error:" + runException.Message);
                    //设置状态
                    state = ConstantHolderUtil.CORE_STATE.CORE_IDLE;
                    //异常暂未处理
                    return 1;
                }
            }
            else
            {
                Helpers.ConsolePrint("XmrStakWin64Helper", "start Miner but busy");
                //状态正忙，不可运行
                return 2;
            }
        }

        /// <summary>
        /// 停止运行
        /// </summary>
        /// <returns></returns>
        public int Stop()
        {
            try
            {
                Helpers.ConsolePrint("XmrStakWin64Helper", "stop Miner");
                //速度清0
                totalSpeed = 0;
                //设置状态
                state = ConstantHolderUtil.CORE_STATE.CORE_IDLE;
                //停止线程
                if (getInfoThread != null && getInfoThread.IsAlive == true)
                {
                    getInfoThread.Abort();
                }

                
                //停止xmr-stak
                Process[] p = Process.GetProcesses();
                foreach (Process p1 in p)
                {
                        string processName = p1.ProcessName.ToLower().Trim();
                        //判断是否包含阻碍更新的进程
                        if (processName == "xmr-stak")
                        {
                            p1.Kill();
                        }
                }
                //停止cmd进程
                if (process.HasExited == false)
                {
                    process.Kill();
                    process.Close();
                }
                if (client != null)
                {
                    isConnect = false;
                    client.Stop();
                    client = null;
                }
                
                return 0;
            }
            catch (Exception stopException)
            {
                Helpers.ConsolePrint("XmrStakWin64Helper", "stop Miner error" + stopException.Message);
                //设置状态
                state = ConstantHolderUtil.CORE_STATE.CORE_BUSY;
                //异常暂未处理
                return 1;
            }
        }

        /// <summary>
        /// 重启cmd
        /// </summary>
        /// <returns></returns>
        private int restart()
        {
            try
            {
                Helpers.ConsolePrint("XmrStakWin64Helper", "restart Miner");
                
                if (client != null)
                {
                    isConnect = false;
                    client.Stop();
                    client = null;
                }
                //停止cmd进程
                if (process.HasExited == false)
                {
                    process.Kill();
                    process.Close();
                }
                //停止xmr-stak
                Process[] p = Process.GetProcesses();
                foreach (Process p1 in p)
                {
                    string processName = p1.ProcessName.ToLower().Trim();
                    //判断是否包含阻碍更新的进程
                    if (processName == "xmr-stak")
                    {
                        p1.Kill();
                    }
                }

                //设置状态
                state = ConstantHolderUtil.CORE_STATE.CORE_IDLE;
                Start(cmdFilePara);
                return 0;
            }
            catch (Exception exception)
            {
                Helpers.ConsolePrint("XmrStakWin64Helper", "restart Miner error" + exception.Message);
                //设置状态
                state = ConstantHolderUtil.CORE_STATE.CORE_BUSY;
                //异常暂未处理
                return 1;
            }
        }

    }
}
